//
//  DroidTextField.swift
//  TextFieldEffects
//
//  Created by yuhus on 2023/7/26.
//

import UIKit

open class DroidTextField: TextFieldEffects {
  open override var placeholder: String? {
    didSet {
      updatePlaceholder()
    }
  }
  
  open var placeholderScale: CGFloat = 0.75 {
    didSet {
      updatePlaceholder()
    }
  }
  
  // MARK: - TextFieldEffects
  
  open override func drawViewsForRect(_ rect: CGRect) {
    placeholderLabel.frame = placeholderRect(forBounds: rect)
    placeholderLabel.textColor = UIColor(red: 0.24, green: 0.24, blue: 0.26, alpha: 0.3)
    
    updatePlaceholder()
    
    addSubview(placeholderLabel)
  }
  
  open override func animateViewsForTextEntry() {
    UIView.animate(withDuration: 0.3) {
      self.updatePlaceholderTransform()
    } completion: { _ in
      self.animationCompletionHandler?(.textEntry)
    }
  }
  
  open override func animateViewsForTextDisplay() {
    guard text?.isEmpty == true else { return }
    UIView.animate(withDuration: 0.3) {
      self.placeholderLabel.transform = .identity
    } completion: { _ in
      self.animationCompletionHandler?(.textDisplay)
    }
  }
  
  // MARK: - Private
  
  open func updatePlaceholder() {
    placeholderLabel.text = placeholder
    placeholderLabel.sizeToFit()
    
    placeholderLabel.transform = .identity
    placeholderLabel.frame = placeholderRect(forBounds: bounds)
    
    if isFirstResponder || text?.isEmpty == false {
      updatePlaceholderTransform()
    }
  }
  
  private func updatePlaceholderTransform() {
    let translationX = placeholderLabel.bounds.width * (1 - placeholderScale) / 2
    let translationY = placeholderLabel.font.lineHeight * (2 - placeholderScale) / 2
    let translate = CGAffineTransform(translationX: -translationX, y: -translationY)
    let scale = CGAffineTransform(scaleX: placeholderScale, y: placeholderScale)
    placeholderLabel.transform = scale.concatenating(translate)
  }
  
  // MARK: - Overrides
  
  open override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    return bounds
  }
  
  open override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return textRect(forBounds: bounds)
  }
  
  open override func textRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.offsetBy(dx: 0, dy: (font?.lineHeight ?? 0) / 2)
  }
}
